﻿using Net5ApiAndEfMySql.DtoModel.Common;
using Net5ApiAndEfMySql.DtoModel.SystemAdmin;
using Net5ApiAndEfMySql.IRepository.SystemAdmin;
using Net5ApiAndEfMySql.IService.SystemAdmin;
using Net5ApiAndEfMySql.PoModel.SystemAdmin;
using Net5CommonLib.SystemLib.Common;
using Net5CommonLib.SystemLib.Tools.TextTools;
using Net5CommonLib.SystemLib.TypeTools;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Net5ApiAndEfMySql.Service.SystemAdmin
{
    public class AdminUserService : BaseService, IAdminUserService
    {
       
        private int expireUserTokenRedisSecond = 2000; //存用户token的redis过期时间,以秒为单位
        public int expireTokenSecond = 1400;  //token过期时间
        private IAdminUserRepository _iAdminUserRepository;
        private string adminUserDtoRedisKey = "saveAdminUserDtoRedisKey";
        //  private RedisManager _redisManager;
        // public AdminUserService(IAdminUserRepository iAdminUserRepository, RedisManager redisManager)
        public AdminUserService(IAdminUserRepository iAdminUserRepository)
        {
            _iAdminUserRepository = iAdminUserRepository;
        }
        public AdminUserPo GetAdminUserByUserName(string userName)
        {
            return _iAdminUserRepository.GetAdminUserByUserName(userName);
        }
        public PagerResult<AdminUserPo> GetPageList(SearchModel m)
        {
            return _iAdminUserRepository.GetPageList(m);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="pwd"></param>
        /// <param name="clientType">客户端类型</param>
        /// <param name="mess"></param>
        /// <returns></returns>
        public AdminUserDto Login(string userName, string pwd, ClientType clientType, out string mess)
        {
            mess = "";
            if (string.IsNullOrEmpty(userName))
            {
                mess = "用户名参数错误";
                return null;
            }
            if (string.IsNullOrEmpty(pwd))
            {
                mess = "密码参数错误";
                return null;
            }
            if (!Enum.IsDefined(typeof(ClientType), clientType))
            {
                mess = "客户端类型不正确";
                return null;
            }
            AdminUserPo adminUser = GetAdminUserByUserName(userName);
            if (adminUser == null)
            {
                mess = "用户名错误";
                return null;
            }
            if (adminUser.pass_word.ToLower() != StringMd5.Md5Hash32Salt(pwd).ToLower())
            {
                mess = "用户名或密码错误";
                return null;
            }

            AdminUserDto adminUserDto = IniUserAndToken(adminUser, clientType);
            mess = "登录成功!";
            return adminUserDto;
        }
        /// <summary>
        /// 获取token
        /// </summary>
        /// <param name="adminUserPo">用户</param>
        /// <param name="clientType">客户端类型</param>
        /// <returns></returns>
        public AdminUserDto IniUserAndToken(AdminUserPo adminUserPo, ClientType clientType)
        {
            //声明用于生成token的对象
            SimpleTokenInfo simpleTokenInfo = new SimpleTokenInfo();
            simpleTokenInfo.UserName = adminUserPo.user_name;
            simpleTokenInfo.ClientType = clientType;
            string token = JwtUtil.Encode(simpleTokenInfo); //加密生成token
            AdminUserDto userAndTokenDto = new AdminUserDto();
            ModelCopier.CopyModel(adminUserPo, userAndTokenDto);

            //#region 权限相关
            //// List<ModuleDbPo> poList = _iModuleService.GetModuleDbsByUserName(userAndTokenDto.user_name);
            ////userAndTokenDto.UserPermission = _iModuleService.GetModuleDtosForModulePos(poList);
            ////  userAndTokenDto.UserPermissionLevel = _iModuleService.IniViewModuleSonByModuleList(poList);
            //#endregion
            ////使用用户名作为redis的key,  clientType 作为hash的key  token作为value, 过期时间为expireSecond变量
            TokenInfo tokenInfo = new TokenInfo();
            tokenInfo.Token = token;
            tokenInfo.ExpireTime = DateTime.Now.AddSeconds(expireTokenSecond);
            RedisManager.HSet(simpleTokenInfo.UserName, clientType.ToString(), tokenInfo);
            RedisManager.HSet(simpleTokenInfo.UserName, adminUserDtoRedisKey, userAndTokenDto, expireUserTokenRedisSecond);
            userAndTokenDto.Token = token;
            return userAndTokenDto;
           
        }


        /// <summary>
        /// 验证token是否有效
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public ResultCode ValidateToken(string token)
        {
            if (GetUserInRedisByToken(token) != null) return ResultCode.Ok;
            return ResultCode.NoLogin;
        }
        /// <summary>
        /// 用token在Resids缓存中获取用户,返回Null代表token无效
        /// </summary>
        /// <param name="token">token</param>
        /// <returns></returns>
        public AdminUserDto GetUserInRedisByToken(string token)
        {
            SimpleTokenInfo simpleTokenInfo = DecodeToken(token);
            if (simpleTokenInfo == null) return null;
            TokenInfo tokenInfo = RedisManager.HGet<TokenInfo>(simpleTokenInfo.UserName, simpleTokenInfo.ClientType.ToString());
           
            if (tokenInfo != null)
            {
                //判断token是否一致,
                //因为同一用户名可能用不同的相同设备登录,所以造成token不一致,要验证token
                if (tokenInfo.Token.Equals(token) && (tokenInfo.ExpireTime - DateTime.Now).TotalSeconds > 0)
                {
                    //刷新时间,这样每次请求接口,都会把过期时间调整为最初时间
                    tokenInfo.ExpireTime = DateTime.Now.AddSeconds(expireTokenSecond);
                    //将最新的token过期时间更新到 redis中
                    RedisManager.HSet(simpleTokenInfo.UserName, simpleTokenInfo.ClientType.ToString(), tokenInfo);

                    AdminUserDto adminUserDto = RedisManager.HGet<AdminUserDto>(simpleTokenInfo.UserName, adminUserDtoRedisKey);
                    //刷新对应redis的过期时间
                    RedisManager.Expire(simpleTokenInfo.UserName, expireUserTokenRedisSecond);
                    adminUserDto.Token = token;
                    return adminUserDto;
                }
                return null;
            }
            return null;
        }
        /// <summary>
        /// 解密token
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public SimpleTokenInfo DecodeToken(string token)
        {
            if (string.IsNullOrEmpty(token)) return null;
            return JwtUtil.Decode<SimpleTokenInfo>(token);
        }

        /// <summary>
        /// 获取与token对应的登录用户信息
        /// </summary>
        /// <param name="token">token</param>
        /// <returns></returns>
        public AdminUserDto GetLoginUserByToken(string token)
        {
            SimpleTokenInfo tokenInfo = DecodeToken(token);
            if (tokenInfo == null) return null;
            AdminUserDto adminUserDto = RedisManager.HGet<AdminUserDto>(tokenInfo.UserName, adminUserDtoRedisKey);
            return adminUserDto;
        }


        /// <summary>
        /// 退出登录
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public bool LoginOut(string token)
        {
            SimpleTokenInfo tokenInfo = DecodeToken(token);
            if (tokenInfo == null) return false;
            return RedisManager.HRemove(tokenInfo.UserName, tokenInfo.ClientType.ToString());
        }


        /// <summary>
        /// 验证用户名是否有效
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public bool ValidateUserName(string userName)
        {
            if (GetAdminUserByUserName(userName) != null) return false ;
            return true;
        }
        /// <summary>
        /// 添加一个用户
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public bool AdminUserAdd(AdminUserDto user)
        {
            if (!ValidateUserName(user.user_name)) return false; //验证用户名是否唯一
            user.creator_date = DateTime.Now;
            user.creator_name = LoginUser.user_name;
            user.pass_word = StringMd5.Md5Hash32Salt(user.pass_word);
            return _iAdminUserRepository.AdminUserAdd(user);
        }

        public bool AdminUserUpdate(AdminUserDto user)
        {
            return _iAdminUserRepository.AdminUserUpdate(user);
        }


        public AdminUserDto GetAdminUserDtoByUserName(string userName)
        {
            return _iAdminUserRepository.GetAdminUserDtoByUserName(userName);
        }



    }
}
